package com.runa.protocol.dto;

import com.runa.protocol.enums.ByteOrder;
import com.runa.protocol.enums.ModbusFunctionCode;
import com.runa.protocol.enums.ModbusType;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.DigitalUtil;
import org.apache.commons.lang3.ArrayUtils;

public abstract class ModbusRequestData extends ModbusData implements IRequestData{

    private int address;

    public ModbusRequestData(int slaveId, ModbusFunctionCode functionCode, int address, ModbusType type) {
        super(type, slaveId, functionCode);
        this.address = address;
    }

    protected abstract byte[] toByteArray();

    @Override
    public byte[] getData() {
        byte[] secOne = new byte[4];
        secOne[0] = (byte) getSlaveId();
        secOne[1] = getFunctionCode().getFunctionCode();
        secOne[2] = (byte) (address >> 8);
        secOne[3] = (byte) (address & 0xff);
        byte[] secTwo = ArrayUtils.addAll(secOne, toByteArray());
        byte[] secThree = null;
        byte[] temp;
        if (ModbusType.MODBUS_RTU.equals(getType())){
            int crc = DigitalUtil.calcCrc16(secTwo, secTwo.length);
            temp = new byte[2];
            temp[0] = (byte) (crc & 0xff);
            temp[1] = (byte) (crc >> 8);
            secThree = ArrayUtils.addAll(secTwo, temp);
        }else if (ModbusType.MODBUS_TCP.equals(getType())){
            temp = new byte[6];
            int len = secTwo.length;
            ByteUtil.shortToByte(getTransSign(), temp, 0, ByteOrder.AB);
            temp[4] = (byte) (len >> 8);
            temp[5] = (byte) (len & 0xff);
            secThree = ArrayUtils.addAll(temp, secTwo);
        }
        return secThree;
    }

    public int getAddress() {
        return address;
    }

    @Override
    public boolean isHaveResult() {
        return true;
    }
}
